/******************************************************************************* * Copyright (c) 2004, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Brock Janiczak (brockj@tpg.com.au) - Bug 145736 *******************************************************************************/ package org.eclipse.ant.internal.ui.antsupport.inputhandler; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.input.DefaultInputHandler; import org.apache.tools.ant.input.InputRequest; import org.apache.tools.ant.input.MultipleChoiceInputRequest; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.FontMetrics; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; public class SWTInputHandler extends DefaultInputHandler { private Text fText; private Combo fCombo; private Text fErrorMessageText; private Button fOkButton; private Shell fDialog; private FontMetrics fFontMetrics; protected InputRequest fRequest; private boolean fFirstValidation = true; /* * (non-Javadoc) * * @see org.apache.tools.ant.input.InputHandler#handleInput(org.apache.tools.ant.input.InputRequest) */ @Override public void handleInput(InputRequest request) throws BuildException { if (System.getProperty("eclipse.ant.noInput") != null) { //$NON-NLS-1$ throw new BuildException(RemoteAntMessages.getString("SWTInputHandler.0")); //$NON-NLS-1$ } fFirstValidation = true; fRequest = request; BuildException[] problem = new BuildException[1]; Runnable runnable = getHandleInputRunnable(problem); Display.getDefault().syncExec(runnable); if (problem[0] != null) { throw problem[0]; } } protected Runnable getHandleInputRunnable(final BuildException[] problem) { return new Runnable() { @Override public void run() { String prompt; if (fRequest instanceof MultipleChoiceInputRequest) { prompt = fRequest.getPrompt(); } else { prompt = getPrompt(fRequest); } String title = RemoteAntMessages.getString("SWTInputHandler.1"); //$NON-NLS-1$ boolean[] result = new boolean[1]; open(title, prompt, result); if (!result[0]) { problem[0] = new BuildException(RemoteAntMessages.getString("SWTInputHandler.2")); //$NON-NLS-1$ } } }; } protected void open(String title, String prompt, boolean[] result) { createDialog(title, prompt, result); validateInput(); fDialog.open(); while (!fDialog.isDisposed()) { if (!fDialog.getDisplay().readAndDispatch()) fDialog.getDisplay().sleep(); } Display.getDefault().dispose(); } private void createDialog(String title, String prompt, boolean[] result) { Display display = Display.getDefault(); fDialog = new Shell(display, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL | SWT.RESIZE); initializeDialogUnits(fDialog); fDialog.setLayout(new GridLayout()); GridData gd = new GridData(SWT.FILL); gd.horizontalSpan = 2; fDialog.setLayoutData(gd); fDialog.setText(title); Label label = new Label(fDialog, SWT.WRAP); label.setText(prompt); GridData data = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_CENTER); data.widthHint = convertHorizontalDLUsToPixels(300); // from IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH label.setLayoutData(data); label.setFont(fDialog.getFont()); if (fRequest instanceof MultipleChoiceInputRequest) { fCombo = new Combo(fDialog, SWT.BORDER | SWT.READ_ONLY); fCombo.add(""); //$NON-NLS-1$ for (String text : ((MultipleChoiceInputRequest) fRequest).getChoices()) { fCombo.add(text); fCombo.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL)); fCombo.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { validateInput(); } }); } } else { fText = new Text(fDialog, SWT.SINGLE | SWT.BORDER); fText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL)); fText.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { validateInput(); } }); } String value = null; try { fRequest.getClass().getMethod("getDefaultValue", new Class<?>[0]); //$NON-NLS-1$ value = fRequest.getDefaultValue(); } catch (SecurityException e) { // do nothing } catch (NoSuchMethodException e) { // pre Ant 1.7.0 } fErrorMessageText = new Text(fDialog, SWT.READ_ONLY); fErrorMessageText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL)); fErrorMessageText.setBackground(display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); createButtonBar(fDialog, result); if (value != null) { if (fCombo != null) { fCombo.select(fCombo.indexOf(value)); } else { fText.setText(value); fText.selectAll(); } } fDialog.pack(); } protected void setErrorMessage(String errorMessage) { fErrorMessageText.setText(errorMessage == null ? "" : errorMessage); //$NON-NLS-1$ fOkButton.setEnabled(errorMessage == null); fErrorMessageText.getParent().update(); } protected void validateInput() { String errorMessage = null; if (fRequest instanceof MultipleChoiceInputRequest) { fRequest.setInput(fCombo.getText()); } else { fRequest.setInput(fText.getText()); } if (!fRequest.isInputValid()) { if (fFirstValidation) { errorMessage = ""; //$NON-NLS-1$ fFirstValidation = false; } else { errorMessage = RemoteAntMessages.getString("SWTInputHandler.3"); //$NON-NLS-1$ } } setErrorMessage(errorMessage); } protected Control createButtonBar(Composite parent, boolean[] result) { Composite composite = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = 2; layout.makeColumnsEqualWidth = true; composite.setLayout(layout); GridData data = new GridData(GridData.HORIZONTAL_ALIGN_END | GridData.VERTICAL_ALIGN_CENTER); composite.setLayoutData(data); composite.setFont(parent.getFont()); createButtonsForButtonBar(composite, result); return composite; } protected void createButtonsForButtonBar(Composite parent, final boolean[] result) { fOkButton = new Button(parent, SWT.PUSH); fOkButton.setText(RemoteAntMessages.getString("SWTInputHandler.4")); //$NON-NLS-1$ setButtonLayoutData(fOkButton); Button cancel = new Button(parent, SWT.PUSH); cancel.setText(RemoteAntMessages.getString("SWTInputHandler.5")); //$NON-NLS-1$ Listener listener = new Listener() { @Override public void handleEvent(Event event) { result[0] = event.widget == fOkButton; fDialog.close(); } }; setButtonLayoutData(cancel); fOkButton.addListener(SWT.Selection, listener); fDialog.setDefaultButton(fOkButton); cancel.addListener(SWT.Selection, listener); // do this here because setting the text will set enablement on the ok button if (fRequest instanceof MultipleChoiceInputRequest) { fCombo.setFocus(); } else { fText.setFocus(); } } private void setButtonLayoutData(Button button) { GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL); int widthHint = convertHorizontalDLUsToPixels(61); // from IDialogConstants.BUTTON_WIDTH Point minSize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); data.widthHint = Math.max(widthHint, minSize.x); button.setLayoutData(data); } private int convertHorizontalDLUsToPixels(int dlus) { // round to the nearest pixel return (fFontMetrics.getAverageCharWidth() * dlus + 4 / 2) / 4; } protected void initializeDialogUnits(Control control) { // Compute and store a font metric GC gc = new GC(control); gc.setFont(control.getFont()); fFontMetrics = gc.getFontMetrics(); gc.dispose(); } }